package com.education.platform.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.education.platform.common.Result;
import com.education.platform.dto.message.MessageSendDTO;
import com.education.platform.dto.message.SystemMessageDTO;
import com.education.platform.entity.Message;
import com.education.platform.service.MessageService;
import com.education.platform.websocket.ChatWebSocketHandler;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 消息控制器
 *
 * @author education-platform
 * @since 2024-10-07
 */
@Tag(name = "消息管理", description = "消息管理相关接口")
@RestController
@RequestMapping("/api/message")
@RequiredArgsConstructor
public class MessageController {

    private final MessageService messageService;
    private final ChatWebSocketHandler chatWebSocketHandler;

    @Operation(summary = "发送消息", description = "发送聊天消息")
    @PostMapping("/send")
    @SaCheckLogin
    public Result<Long> sendMessage(@Validated @RequestBody MessageSendDTO messageSendDTO) {
        Long fromUserId = StpUtil.getLoginIdAsLong();
        Long messageId = messageService.sendMessage(
                fromUserId, 
                messageSendDTO.getToUserId(), 
                messageSendDTO.getContent(),
                messageSendDTO.getContentType(),
                messageSendDTO.getExtraData()
        );
        return Result.success(messageId);
    }

    @Operation(summary = "发送系统消息", description = "发送系统消息（管理员）")
    @PostMapping("/system")
    @SaCheckRole("ADMIN")
    public Result<Void> sendSystemMessage(@Validated @RequestBody SystemMessageDTO systemMessageDTO) {
        if ("ALL".equals(systemMessageDTO.getRecipientType())) {
            // 广播消息
            messageService.broadcastMessage(
                    systemMessageDTO.getTitle(),
                    systemMessageDTO.getContent(),
                    systemMessageDTO.getExtraData()
            );
        } else if (systemMessageDTO.getUserIds() != null && !systemMessageDTO.getUserIds().isEmpty()) {
            // 批量发送
            messageService.batchSendSystemMessage(
                    systemMessageDTO.getUserIds(),
                    systemMessageDTO.getTitle(),
                    systemMessageDTO.getContent(),
                    systemMessageDTO.getExtraData()
            );
        }
        return Result.success();
    }

    @Operation(summary = "标记消息为已读", description = "标记消息为已读")
    @PostMapping("/{id}/read")
    @SaCheckLogin
    public Result<Void> markAsRead(@PathVariable Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        messageService.markMessageAsRead(id, userId);
        return Result.success();
    }

    @Operation(summary = "批量标记为已读", description = "批量标记消息为已读")
    @PostMapping("/batch-read")
    @SaCheckLogin
    public Result<Void> batchMarkAsRead(@RequestBody List<Long> messageIds) {
        Long userId = StpUtil.getLoginIdAsLong();
        messageService.batchMarkAsRead(messageIds, userId);
        return Result.success();
    }

    @Operation(summary = "标记会话为已读", description = "标记会话中的所有消息为已读")
    @PostMapping("/conversation/{conversationId}/read")
    @SaCheckLogin
    public Result<Void> markConversationAsRead(@PathVariable String conversationId) {
        Long userId = StpUtil.getLoginIdAsLong();
        messageService.markConversationAsRead(conversationId, userId);
        return Result.success();
    }

    @Operation(summary = "删除消息", description = "删除消息")
    @DeleteMapping("/{id}")
    @SaCheckLogin
    public Result<Void> deleteMessage(@PathVariable Long id) {
        Long userId = StpUtil.getLoginIdAsLong();
        messageService.deleteMessage(id, userId);
        return Result.success();
    }

    @Operation(summary = "获取消息详情", description = "根据ID获取消息详细信息")
    @GetMapping("/{id}")
    @SaCheckLogin
    public Result<Message> getMessageDetail(@PathVariable Long id) {
        Message message = messageService.getMessageById(id);
        return Result.success(message);
    }

    @Operation(summary = "分页查询消息列表", description = "分页查询消息列表")
    @GetMapping("/page")
    @SaCheckLogin
    public Result<IPage<Message>> getMessagePage(
            @RequestParam(defaultValue = "1") Integer current,
            @RequestParam(defaultValue = "20") Integer size,
            @RequestParam(required = false) String conversationId,
            @RequestParam(required = false) String type,
            @RequestParam(required = false) String status) {
        Long userId = StpUtil.getLoginIdAsLong();
        Page<Message> page = new Page<>(current, size);
        IPage<Message> result = messageService.getMessagePage(page, userId, conversationId, type, status);
        return Result.success(result);
    }

    @Operation(summary = "获取会话消息", description = "获取指定会话的消息列表")
    @GetMapping("/conversation/{conversationId}")
    @SaCheckLogin
    public Result<List<Message>> getConversationMessages(
            @PathVariable String conversationId,
            @RequestParam(defaultValue = "50") Integer limit) {
        List<Message> messages = messageService.getConversationMessages(conversationId, limit);
        return Result.success(messages);
    }

    @Operation(summary = "获取未读消息", description = "获取当前用户的未读消息")
    @GetMapping("/unread")
    @SaCheckLogin
    public Result<List<Message>> getUnreadMessages() {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Message> messages = messageService.getUnreadMessages(userId);
        return Result.success(messages);
    }

    @Operation(summary = "统计未读消息数量", description = "统计当前用户的未读消息数量")
    @GetMapping("/unread/count")
    @SaCheckLogin
    public Result<Integer> countUnreadMessages() {
        Long userId = StpUtil.getLoginIdAsLong();
        Integer count = messageService.countUnreadMessages(userId);
        return Result.success(count);
    }

    @Operation(summary = "统计会话未读数量", description = "统计指定会话的未读消息数量")
    @GetMapping("/conversation/{conversationId}/unread/count")
    @SaCheckLogin
    public Result<Integer> countUnreadByConversation(@PathVariable String conversationId) {
        Long userId = StpUtil.getLoginIdAsLong();
        Integer count = messageService.countUnreadByConversation(conversationId, userId);
        return Result.success(count);
    }

    @Operation(summary = "获取系统消息", description = "获取系统消息列表")
    @GetMapping("/system")
    @SaCheckLogin
    public Result<List<Message>> getSystemMessages(@RequestParam(defaultValue = "20") Integer limit) {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Message> messages = messageService.getSystemMessages(userId, limit);
        return Result.success(messages);
    }

    @Operation(summary = "获取最近聊天用户", description = "获取最近聊天的用户列表")
    @GetMapping("/recent-chats")
    @SaCheckLogin
    public Result<List<Message>> getRecentChatUsers(@RequestParam(defaultValue = "10") Integer limit) {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Message> messages = messageService.getRecentChatUsers(userId, limit);
        return Result.success(messages);
    }

    @Operation(summary = "获取在线用户", description = "获取当前在线用户列表（管理员）")
    @GetMapping("/online-users")
    @SaCheckRole("ADMIN")
    public Result<java.util.Set<Long>> getOnlineUsers() {
        java.util.Set<Long> onlineUsers = chatWebSocketHandler.getOnlineUsers();
        return Result.success(onlineUsers);
    }

    @Operation(summary = "检查用户在线状态", description = "检查指定用户是否在线")
    @GetMapping("/user/{userId}/online")
    @SaCheckLogin
    public Result<Boolean> isUserOnline(@PathVariable Long userId) {
        Boolean isOnline = chatWebSocketHandler.isUserOnline(userId);
        return Result.success(isOnline);
    }

    @Operation(summary = "清理过期消息", description = "清理过期消息（管理员）")
    @DeleteMapping("/clean")
    @SaCheckRole("ADMIN")
    public Result<Void> cleanExpiredMessages(@RequestParam(defaultValue = "30") Integer days) {
        messageService.cleanExpiredMessages(days);
        return Result.success();
    }
}
